#include "PagingSystem.h"
#include "GameSceneManager.h"
#include "GameSystemManager.h"
#include "TerrainSystem.h"
#include "GameObjectManager.h"
#include "TextOutput.h"

#include "heightFunction.h"

std::map<std::string,PagedObjects*> mFoliage;
Paging_Config PagingConfig;

bool PagingSystem::running = false;

PagedObjects::PagedObjects() { }
PagedObjects::~PagedObjects() { }

PagingSystem::PagingSystem()
{
	//addResources();

	//Setup Ogre::Root and the scene manager
	root = GameSystemManager::getSingleton()->getOgre()->getRoot();
	window = GameSystemManager::getSingleton()->getOgre()->getWindow();
	sceneMgr = GameSceneManager::getSingleton()->getSceneManager();
	camera = GameSceneManager::getSingleton()->getCamera();
	viewport = GameSceneManager::getSingleton()->getViewport();
	running = true;
	
	PagingConfig.paintMode = true;
	PagingConfig.eraseMode = false;

	/*
	//Load media (trees, grass, etc.)
	ResourceGroupManager::getSingleton().addResourceLocation("../../media/trees2", "FileSystem");
	ResourceGroupManager::getSingleton().addResourceLocation("../../media/terrain2", "FileSystem");
	ResourceGroupManager::getSingleton().addResourceLocation("../../media/grass", "FileSystem");
	ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
	*/

	/*
	//Initialize OIS
	size_t windowHnd;
	window->getCustomAttribute("WINDOW", &windowHnd);
	inputManager = OIS::InputManager::createInputSystem(windowHnd);
	
	keyboard = (OIS::Keyboard*)inputManager->createInputObject(OIS::OISKeyboard, false);
	mouse = (OIS::Mouse*)inputManager->createInputObject(OIS::OISMouse, false);
	*/
	//Reset camera orientation
	camPitch = 0;
	camYaw = 0;

	//load();		//Load world
	//run();		//Display world

}

PagingSystem::~PagingSystem()
{
	//Shut down OIS
	//inputManager->destroyInputObject(keyboard);
	//inputManager->destroyInputObject(mouse);
	//OIS::InputManager::destroyInputSystem(inputManager);

	unload();
}

std::map<std::string,PagedObjects*> PagingSystem::getFoliage() {
	return mFoliage;
}
PagedObjects* PagingSystem::getFoliageByName(std::string name) {
	return mFoliage[name];
}

void PagingSystem::removePagedObject(std::string name) {
	std::map<std::string, PagedObjects*>::iterator iter = mFoliage.begin();
	iter = mFoliage.find(name);
	
	if(iter != mFoliage.end()) {
		sceneMgr->destroyEntity(iter->second->entityName);
		delete iter->second->geometry->getPageLoader();
		delete iter->second->geometry;
		mFoliage.erase(iter);
		PagingConfig.selectedPagedTrees = "";
	}	
}
void PagingSystem::removeAllPagedObjects() {
	std::map<std::string, PagedObjects*>::iterator iter;
	for(iter = mFoliage.begin(); iter != mFoliage.end(); iter++) {
		if(iter->second) {
			sceneMgr->destroyEntity(iter->second->entityName);
			delete iter->second->geometry->getPageLoader();
			delete iter->second->geometry;
		}
	}
	mFoliage.clear();
}

//[NOTE] In addition to some Ogre setup, this function configures PagedGeometry in the scene.
/*
void PagingSystem::load()
{
	//-------------------------------------- LOAD TERRAIN --------------------------------------
	//Setup the fog up to 1500 units away
	//sceneMgr->setFog(FOG_LINEAR, viewport->getBackgroundColour(), 0, 100, 900);

	//Load the terrain
	//sceneMgr->setWorldGeometry("terrain2.cfg");

	//Start off with the camera at the center of the terrain
	//camera->setPosition(700, 100, 700);

	//Setup a skybox
	//sceneMgr->setSkyBox(true, "3D-Diggers/SkyBox", 2000);

	//-------------------------------------- LOAD GRASS --------------------------------------
	//Create and configure a new PagedGeometry instance for grass
	grass = new PagedGeometry(camera, 30);
	grass->addDetailLevel<GrassPage>(60);

	//Create a GrassLoader object
	grassLoader = new GrassLoader(grass);
	grass->setPageLoader(grassLoader);	//Assign the "treeLoader" to be used to load geometry for the PagedGeometry instance

	//Supply a height function to GrassLoader so it can calculate grass Y values
	HeightFunction::initialize(sceneMgr);
	grassLoader->setHeightFunction(&HeightFunction::getTerrainHeight);

	//Add some grass to the scene with GrassLoader::addLayer()
	GrassLayer *l = grassLoader->addLayer("3D-Diggers/plant1sprite");

	//Configure the grass layer properties (size, density, animation properties, fade settings, etc.)
	l->setMinimumSize(0.7f, 0.7f);
	l->setMaximumSize(0.9f, 0.9f);
	l->setAnimationEnabled(true);		//Enable animations
	l->setSwayDistribution(7.0f);		//Sway fairly unsynchronized
	l->setSwayLength(0.1f);				//Sway back and forth 0.5 units in length
	l->setSwaySpeed(0.4f);				//Sway 1/2 a cycle every second
	//l->setDensity(0.005f);				//Relatively dense grass
	l->setDensity(0.05f);				//Relatively dense grass
	
	l->setRenderTechnique(GRASSTECH_SPRITE);
	//GRASSTECH_QUAD,
	//GRASSTECH_CROSSQUADS,
	//GRASSTECH_SPRITE

	l->setFadeTechnique(FADETECH_GROW);	//Distant grass should slowly raise out of the ground when coming in range

	//[NOTE] This sets the color map, or lightmap to be used for grass. All grass will be colored according
	//to this texture. In this case, the colors of the terrain is used so grass will be shadowed/colored
	//just as the terrain is (this usually makes the grass fit in very well).
	l->setColorMap("terrain_texture2.jpg");

	//This sets the density map that will be used to determine the density levels of grass all over the
	//terrain. This can be used to make grass grow anywhere you want to; in this case it's used to make
	//grass grow only on fairly level ground (see densitymap.png to see how this works).
	

	l->setDensityMap("densitymap.png");

	//setMapBounds() must be called for the density and color maps to work (otherwise GrassLoader wouldn't
	//have any knowledge of where you want the maps to be applied). In this case, the maps are applied
	//to the same boundaries as the terrain.
	//l->setMapBounds(TBounds(0, 0, 1500, 1500));	//(0,0)-(1500,1500) is the full boundaries of the terrain
	Ogre::Real mapboundX,mapboundY;
	mapboundX = mapboundY = 1000; // OK = 993; // ERROR = 994
	l->setMapBounds(TBounds(0, 0, mapboundX-7, mapboundY-7));	//(0,0)-(1500,1500) is the full boundaries of the terrain

	//-------------------------------------- LOAD TREES --------------------------------------
	//Create and configure a new PagedGeometry instance
	trees = new PagedGeometry();
	trees->setCamera(camera);	//Set the camera so PagedGeometry knows how to calculate LODs
	trees->setPageSize(50);	//Set the size of each page of geometry
	trees->setInfinite();		//Use infinite paging mode
	trees->addDetailLevel<BatchPage>(90, 30);		//Use batches up to 150 units away, and fade for 30 more units
	trees->addDetailLevel<ImpostorPage>(700, 50);	//Use impostors up to 400 units, and for for 50 more units

	//Create a new TreeLoader2D object
	TreeLoader2D *treeLoader = new TreeLoader2D(trees, TBounds(0, 0, mapboundX-50, mapboundY-50));
	trees->setPageLoader(treeLoader);	//Assign the "treeLoader" to be used to load geometry for the PagedGeometry instance

	//Supply a height function to TreeLoader2D so it can calculate tree Y values
	HeightFunction::initialize(sceneMgr);
	treeLoader->setHeightFunction(&HeightFunction::getTerrainHeight);

	//[NOTE] This sets the color map, or lightmap to be used for trees. All trees will be colored according
	//to this texture. In this case, the shading of the terrain is used so trees will be shadowed
	//just as the terrain is (this should appear like the terrain is casting shadows on the trees).
	//You may notice that TreeLoader2D / TreeLoader3D doesn't have a setMapBounds() function as GrassLoader
	//does. This is because the bounds you specify in the TreeLoader2D constructor are used to apply
	//the color map.
	treeLoader->setColorMap("terrain_lightmap.jpg");

	//Load a tree entity
	Entity *tree1 = sceneMgr->createEntity("Tree1", "fir05_30.mesh");
	Entity *tree2 = sceneMgr->createEntity("Tree2", "fir06_30.mesh");
	Entity *tree3 = sceneMgr->createEntity("Tree3", "fir14_25.mesh");

	//Randomly place 10000 copies of the tree on the terrain
	Ogre::Vector3 position = Ogre::Vector3::ZERO;
	Radian yaw;
	Real scale;
	for (int i = 0; i < 200; i++){
		yaw = Degree(Math::RangeRandom(0, 360));

		position.x = Math::RangeRandom(0, mapboundX-50);
		position.z = Math::RangeRandom(0, mapboundY-50);
		//position.y = GameSystemManager::getSingleton()->getTerrain()->getTerrainHeightAt(position.x,position.z);

		scale = Math::RangeRandom(0.07f, 0.12f);

		//[NOTE] Unlike TreeLoader3D, TreeLoader2D's addTree() function accepts a Vector2D position (x/z)
		//The Y value is calculated during runtime (to save memory) from the height function supplied (above)
		//Real rnd = Math::UnitRandom();
		Real rnd = Math::RangeRandom(0,3);

		if (rnd < 1) {
			treeLoader->addTree(tree1, position, yaw, scale);
		} else if(rnd >= 1 && rnd < 2) {
			treeLoader->addTree(tree2, position, yaw, scale);
		} else if(rnd >= 2) {
			treeLoader->addTree(tree3, position, yaw, scale);
		}
	}

	//-------------------------------------- LOAD BUSHES --------------------------------------
	//Create and configure a new PagedGeometry instance for bushes
	bushes = new PagedGeometry(camera, 50);
	
	//bushes->setBounds(TBounds(0, 0, mapboundX-50, mapboundY));

	bushes->addDetailLevel<BatchPage>(80, 50);

	//Create a new TreeLoader2D object for the bushes
	TreeLoader2D *bushLoader = new TreeLoader2D(bushes, TBounds(0, 0, mapboundX-50, mapboundY-50));
	bushes->setPageLoader(bushLoader);
	
	//Supply the height function to TreeLoader2D so it can calculate tree Y values
	HeightFunction::initialize(sceneMgr);
	bushLoader->setHeightFunction(&HeightFunction::getTerrainHeight);

	//bushLoader->setColorMap("terrain_lightmap.jpg");

	//Load a bush entity
	Entity *fern = sceneMgr->createEntity("Fern", "farn1.mesh");
	Entity *plant = sceneMgr->createEntity("Plant", "plant2.mesh");
	Entity *mushroom = sceneMgr->createEntity("Mushroom", "shroom1_1.mesh");

	//Randomly place 20,000 bushes on the terrain
	for (int i = 0; i < 200; i++){
		yaw = Degree(Math::RangeRandom(0, 360));
		position.x = Math::RangeRandom(0, mapboundX-50);
		position.z = Math::RangeRandom(0, mapboundY-50);
		//position.y = GameSystemManager::getSingleton()->getTerrain()->getTerrainHeightAt(position.x,position.z);

		float rnd = Math::UnitRandom();
		if (rnd < 0.8f) {
			scale = Math::RangeRandom(0.3f, 0.4f);
			bushLoader->addTree(fern, position, yaw, scale);
		} else if (rnd < 0.9) {
			scale = Math::RangeRandom(0.1f, 0.3f);
			bushLoader->addTree(mushroom, position, yaw, scale);
		} else {
			scale = Math::RangeRandom(0.3f, 0.5f);
			bushLoader->addTree(plant, position, yaw, scale);
		}
	}
	running = true;
}
*/

/*
void PagingSystem::addResources() {

	StringVectorPtr resourceNames = ResourceGroupManager::getSingleton().getre findResourceNames("PagedGeometry","",true );
	std::vector<Ogre::String>::const_iterator itResourceName = resourceNames->begin();
	if( itResourceName != resourceNames->end() ) {
		std::string treeDirName = itResourceName->c_str();
		ResourceGroupManager::getSingleton().addResourceLocation(treeDirName, "FileSystem", "PagedGeometry");
	}

	resourceNames = ResourceGroupManager::getSingleton().findResourceNames("PagedGeometry","Trees/*.mesh",false );
	itResourceName = resourceNames->begin();
	while ( itResourceName != resourceNames->end() )
	{
		//std::string meshName = itResourceName->substr(6,itResourceName->length() - 6);
		std::string meshName = itResourceName->c_str(); //itResourceName->c_str()
		ResourceGroupManager::getSingleton().addResourceLocation(meshName, "FileSystem", "PagedGeometry");
		++itResourceName;
	} 

}
*/
PagedGeometry* PagingSystem::addGrassPage(std::string name,Real pageSize,Real batchDistance, std::string materialName, Real minScale, Real maxScale, bool animated, Real swayLenght, Real swaySpeed, Real density, GrassTechnique grt, FadeTechnique ft) {

	PagedObjects *po = getFoliageByName(name);
	if(po) {
		OgreQueueText::instance()->Add("Paged Object with that name already exists");
		return NULL;
	}

	po = new PagedObjects();

	po->name = name;
	po->isGrass = true;
	po->isTree = false;
	po->pageSize = pageSize;
	po->batchDistance = batchDistance;
	po->materialName = materialName;
	po->minScale = minScale;
	po->maxScale = maxScale;
	po->animated = animated;
	po->swayLenght = swayLenght;
	po->swaySpeed = swaySpeed;
	po->density = density;
	po->grt = grt;
	po->ft = ft;
	po->pageBounds = TBounds(0, 0, 
		(terrain_config.mTerrainSizeX) - 7, 
		(terrain_config.mTerrainSizeX) - 7); //Now only square terrains supported, kinda sucks
		//GameSystemManager::getSingleton()->getSystem("TerrainSystem")->getParam("terrainSizeZ")->toFloat()-7);

	PagedGeometry *grass = new PagedGeometry(camera, pageSize);
	grass->addDetailLevel<GrassPage>(batchDistance);

	po->grassLoader = new GrassLoader(grass);
	grass->setPageLoader(po->grassLoader);	//Assign the "treeLoader" to be used to load geometry for the PagedGeometry instance

	HeightFunction::initialize(sceneMgr);
	po->grassLoader->setHeightFunction(&HeightFunction::getTerrainHeight);

	po->grassLayer = po->grassLoader->addLayer(materialName);

	po->grassLayer->setMinimumSize(minScale, minScale);
	po->grassLayer->setMaximumSize(maxScale, maxScale);
	po->grassLayer->setAnimationEnabled(animated);		//Enable animations
	po->grassLayer->setSwayDistribution(7.0f);		//Sway fairly unsynchronized
	po->grassLayer->setSwayLength(swayLenght);				//Sway back and forth 0.5 units in length
	po->grassLayer->setSwaySpeed(swaySpeed);				//Sway 1/2 a cycle every second
	po->grassLayer->setDensity(density);				//Relatively dense grass
	po->grassLayer->setRenderTechnique(grt);
	po->grassLayer->setFadeTechnique(ft);	//Distant grass should slowly raise out of the ground when coming in range
	po->grassLayer->setColorMap("terrain_texture2.jpg");
	
	//std::string densityMapName = "densitymap" + 
	Real rnd = (Math::UnitRandom()); //(1, 4));
	Ogre::String dmap;
	if(rnd <= 0.25)
		dmap = "densitymap1.png";
	if(rnd > 0.25 && rnd <= 0.5)
		dmap = "densitymap2.png";
	if(rnd > 0.5 && rnd <= 0.75)
		dmap = "densitymap3.png";
	if(rnd > 0.75)
		dmap = "densitymap4.png";

	MapChannel mc;
	rnd = (Math::UnitRandom()); //(1, 4));
	if(rnd <= 0.25)
		mc = CHANNEL_ALPHA;
	if(rnd > 0.25 && rnd <= 0.5)
		mc = CHANNEL_BLUE;
	if(rnd > 0.5 && rnd <= 0.75)
		mc = CHANNEL_GREEN;
	if(rnd > 0.75)
		mc = CHANNEL_RED;

	po->grassLayer->setDensityMap(dmap,mc);
	
	
	po->grassLayer->setMapBounds(po->pageBounds);

	po->geometry = grass;

	mFoliage[name] = po;

	return grass;
}

void PagingSystem::updateTreeBrush() {
	
	if (GameSystemManager::getSingleton()->getInput()->isLeftButtonDown() &&  terrain_config.mIsTerrainLoaded )
	{
		if(GameSceneManager::getSingleton()->getBrush() == BRUSH_FOLIAGE)
		{
			treeBrush();
		}

	}
}

void PagingSystem::treeBrush() {
	if(PagingConfig.selectedPagedTrees!= "") {
		PagedObjects *po = getFoliageByName(PagingConfig.selectedPagedTrees);
		if(po) {

			Degree yaw = Degree(Math::RangeRandom(0, 360));

			Real scale = Math::RangeRandom(po->minScale,po->maxScale);

			//Vector3 pos = GameSystemManager::getSingleton()->getTerrain()->mPointer->getPosition();
			
			Vector3 pos = GameSystemManager::getSingleton()->getTerrain()->mPointer->getPosition();

			Radian rndAng = Radian(Math::RangeRandom(0, Math::TWO_PI));
			Real rndLen = Math::RangeRandom(0,PagingConfig.brushHeight);
			pos.x += Math::Sin(rndAng) * rndLen;
			pos.z += Math::Cos(rndAng) * rndLen;
			
			if(PagingConfig.paintMode)
				po->treeLoader->addTree(po->entity, pos, yaw, scale);

			if(PagingConfig.eraseMode)
				po->treeLoader->deleteTrees(pos,PagingConfig.brushHeight);

		}
	}
}

PagedGeometry* PagingSystem::addTreePage(std::string name,Real pageSize,Real batchDistance, Real batchFade, Real impostorDist, Real impostorFade, std::string meshName, unsigned int quantity, Real minScale, Real maxScale) {

	PagedObjects *po = getFoliageByName(name);
	if(po) {
		OgreQueueText::instance()->Add("Paged Object with that name already exists");
		return NULL;
	}

	PagedGeometry *trees = new PagedGeometry();
	
	po = new PagedObjects();
	
	po->name = name;
	po->meshName = meshName;
	po->pageSize = pageSize;
	po->batchDistance = batchDistance;
	po->batchFade = batchFade;
	po->impostorDist = impostorDist;
	po->impostorFade = impostorFade;
	po->quantity = quantity;
	po->minScale = minScale;
	po->maxScale = maxScale;

	trees->setCamera(camera);	//Set the camera so PagedGeometry knows how to calculate LODs
	trees->setPageSize(pageSize);	//Set the size of each page of geometry
	trees->setInfinite();		//Use infinite paging mode
	trees->addDetailLevel<BatchPage>(batchDistance, batchFade);		//Use batches up to 150 units away, and fade for 30 more units
	trees->addDetailLevel<ImpostorPage>(impostorDist, impostorFade);	//Use impostors up to 400 units, and for for 50 more units

	Real terrX = terrain_config.mTerrainSizeX;
	Real terrZ = terrain_config.mTerrainSizeZ;

	//Real terrX = GameSystemManager::getSingleton()->getSystem("TerrainSystem")->getParam("terrainSizeX")->toFloat();
	//Real terrZ = GameSystemManager::getSingleton()->getSystem("TerrainSystem")->getParam("terrainSizeZ")->toFloat();

	po->pageBounds = TBounds(0, 0, terrX-50, terrZ-50);

	TreeLoader2D *treeLoader = new TreeLoader2D(trees, po->pageBounds);
	trees->setPageLoader(treeLoader);	//Assign the "treeLoader" to be used to load geometry for the PagedGeometry instance

	HeightFunction::initialize(sceneMgr);
	treeLoader->setHeightFunction(&HeightFunction::getTerrainHeight);

	treeLoader->setColorMap("terrain_lightmap.jpg");

	po->entityName = "Foliage" + GameObjectManager::getSingleton()->getNextCompIndex();
	po->entity = sceneMgr->createEntity(po->entityName, meshName);
	po->isTree = true;
	po->isGrass = false;
	po->geometry = trees;
	po->treeLoader = treeLoader;

	mFoliage[name] = po;

	return trees;
}

void PagingSystem::randomizeTreePage(std::string name) {
	if(name != "") {
		if(!mFoliage[name])
			return;
		Ogre::Vector3 position = Ogre::Vector3::ZERO;
		Radian yaw;
		Real scale;
		for (unsigned int i = 0; i < mFoliage[name]->quantity; i++){
			yaw = Degree(Math::RangeRandom(0, 360));

			Real terrX = terrain_config.mTerrainSizeX;
			Real terrZ = terrain_config.mTerrainSizeZ;

			//Real terrX = GameSystemManager::getSingleton()->-->getParam("terrainSizeX")->toFloat();
			//Real terrZ = GameSystemManager::getSingleton()->getSystem("TerrainSystem")->getParam("terrainSizeZ")->toFloat();

			position.x = Math::RangeRandom(0,terrX-50);
			position.z = Math::RangeRandom(0,terrZ-50);

			scale = Math::RangeRandom(mFoliage[name]->minScale, mFoliage[name]->maxScale);

			mFoliage[name]->position = position;
			mFoliage[name]->treeLoader->addTree(mFoliage[name]->entity, position, yaw, scale);
		}
	}
}

void PagingSystem::addSingleTreePage(std::string pageName,Vector3 pos) {
	if(mFoliage[pageName]) {
		Radian yaw;
		Real scale;
		//for (unsigned int i = 0; i < mFoliage[pageName]->quantity; i++){
			
			yaw = Degree(Math::RangeRandom(0, 360));

			Real terrX = terrain_config.mTerrainSizeX;
			Real terrZ = terrain_config.mTerrainSizeZ;

			//position.x = Math::RangeRandom(0,terrX-50);
			//position.z = Math::RangeRandom(0,terrZ-50);

			scale = Math::RangeRandom(mFoliage[pageName]->minScale, mFoliage[pageName]->maxScale);

			mFoliage[pageName]->position = pos;
			mFoliage[pageName]->treeLoader->addTree(mFoliage[pageName]->entity, pos, yaw, scale);
			//->getAttachedObjectIterator()


				// do whatever there is to do with the entity...
			

		//}
	}
}

void PagingSystem::unload()
{
	//[NOTE] Always remember to delete any PageLoader(s) and PagedGeometry instances to avoid memory leaks.

	//Delete the PageLoader's
	//delete grass->getPageLoader();
	//delete trees->getPageLoader();
	//delete bushes->getPageLoader();

	//Delete the PagedGeometry instances
	//delete grass;
	//delete trees;
	//delete bushes;

	//Also delete the entities
	//sceneMgr->destroyEntity("Tree1");
	//sceneMgr->destroyEntity("Fern");
	//sceneMgr->destroyEntity("Plant");
	//sceneMgr->destroyEntity("Mushroom");
}
void PagingSystem::setBrushSize(Real size) {
	
	bool terrainLoaded = terrain_config.mIsTerrainLoaded;

	if(!terrainLoaded || size == 0)
		return;
	
	PagingConfig.brushHeight = size;
	PagingConfig.brushWidth = size;

	GameSystemManager::getSingleton()->getTerrain()->mPincelDecal->setSize(Vector2(size * 2,size * 2));

	//static_cast<TerrainSystem*>(GameSystemManager::getSingleton()->getSystem("TerrainSystem"))->mPincelDecal->setSize(Vector2(size * 2,size * 2));
	//GameSystemManager::getSingleton()->getTerrain()->mPincelDecal->setSize(Vector2(size * 2,size * 2));

}
void PagingSystem::update()
{
	if(running) {
		render();
		updateTreeBrush();
	}
}

void PagingSystem::render()
{
	//[NOTE] PagedGeometry::update() is called every frame to keep LODs, etc. up-to-date
	//grass->update();
	//trees->update();
	//bushes->update();

	std::map<std::string, PagedObjects*>::iterator iter;
	for(iter = mFoliage.begin(); iter != mFoliage.end(); iter++) {
		iter->second->geometry->update(); // second->update();
	}

}
void PagingSystem::loadGameObjectsToXML(TiXmlElement* mElem)
{
	bool isTree;

	std::string name;
	Real pageSize;
	Real batchDistance;
	std::string materialName;
	Real minScale;
	Real maxScale;
	bool animated;
	Real swayLenght;
	Real swaySpeed;
	Real density;
	GrassTechnique grt;
	FadeTechnique ft;
	
	std::string meshName;
	Real batchFade;
	Real impostorDist;
	Real impostorFade;
	unsigned int quantity;

	TiXmlHandle hRoot(0);
	hRoot = TiXmlHandle(mElem);

	int i = 0;

	TiXmlElement* mObjElem = hRoot.Child("PagedObject",0).Element();

	while (mObjElem) {

		//Get object name and store it
		TiXmlAttribute* mObjAttrib; 
		mObjAttrib = mObjElem->FirstAttribute();
		if(mObjAttrib)
			name = mObjAttrib->Value();
		else
			break;

		isTree = Ogre::StringConverter::parseBool(mObjElem->Attribute("isTree"));

		if(isTree) {
			
			pageSize = Ogre::StringConverter::parseReal(mObjElem->Attribute("pageSize"));
			batchDistance = Ogre::StringConverter::parseReal(mObjElem->Attribute("batchDistance"));
			batchFade = Ogre::StringConverter::parseReal(mObjElem->Attribute("batchFade"));
			impostorDist = Ogre::StringConverter::parseReal(mObjElem->Attribute("impostorDist"));
			impostorFade = Ogre::StringConverter::parseReal(mObjElem->Attribute("impostorFade"));
			meshName = mObjElem->Attribute("meshName");
			quantity = Ogre::StringConverter::parseReal(mObjElem->Attribute("quantity"));
			minScale = Ogre::StringConverter::parseReal(mObjElem->Attribute("minScale"));
			maxScale = Ogre::StringConverter::parseReal(mObjElem->Attribute("maxScale"));

			//Add the page
			GameSystemManager::getSingleton()->getPaging()->addTreePage(name,pageSize,batchDistance,batchFade,impostorDist,impostorFade,meshName,quantity,minScale,maxScale);

			TiXmlElement* mTreeElem;
			TiXmlHandle hPagedObjectRoot(0);
			hPagedObjectRoot = TiXmlHandle(mObjElem);
			int i = 0;
			mTreeElem = hPagedObjectRoot.Child("Tree",0).Element();

			while(mTreeElem) {
				//Then load each tree of the page, must match with .quantity of the xml file
				Vector3 pos;
				if(mTreeElem)
					pos = Ogre::StringConverter::parseVector3(mTreeElem->Attribute("position"));

				GameSystemManager::getSingleton()->getPaging()->addSingleTreePage(name,pos);

				i++;
				mTreeElem = hPagedObjectRoot.Child("Tree",i).Element();
				
			}

		} else {
			pageSize = Ogre::StringConverter::parseReal(mObjElem->Attribute("pageSize"));
			batchDistance = Ogre::StringConverter::parseReal(mObjElem->Attribute("batchDistance"));
			materialName = mObjElem->Attribute("materialName");
			minScale = Ogre::StringConverter::parseReal(mObjElem->Attribute("minScale"));
			maxScale = Ogre::StringConverter::parseReal(mObjElem->Attribute("maxScale"));
			animated = Ogre::StringConverter::parseReal(mObjElem->Attribute("animated"));
			swayLenght = Ogre::StringConverter::parseReal(mObjElem->Attribute("swayLenght"));
			swaySpeed = Ogre::StringConverter::parseReal(mObjElem->Attribute("swaySpeed"));
			density = Ogre::StringConverter::parseReal(mObjElem->Attribute("density"));
			
			std::string grassTech = mObjElem->Attribute("GrassTechnique");

			if(grassTech == "GRASSTECH_QUAD")
				grt = GRASSTECH_QUAD;
			if(grassTech == "GRASSTECH_CROSSQUADS")
				grt = GRASSTECH_CROSSQUADS;
			if(grassTech == "GRASSTECH_SPRITE")
				grt = GRASSTECH_SPRITE;

			std::string fadeTech = mObjElem->Attribute("FadeTechnique");

			if(fadeTech == "FADETECH_ALPHA")
				ft = FADETECH_ALPHA;
			if(fadeTech == "FADETECH_ALPHAGROW")
				ft = FADETECH_ALPHAGROW;
			if(fadeTech == "FADETECH_GROW")
				ft = FADETECH_GROW;

			GameSystemManager::getSingleton()->getPaging()->addGrassPage(name,pageSize,batchDistance,materialName,minScale,maxScale,animated,swayLenght,swaySpeed,density,grt,ft);
			
		}
		GameSystemManager::getSingleton()->getGUI()->updatePagedObjects();

		i++;
		mObjElem = hRoot.Child("PagedObject",i).Element();

	}

	GameSystemManager::getSingleton()->getGUI()->updateGameObjects();
	
}

void PagingSystem::saveGameObjectsToXML(TiXmlElement* mElem)
{

	//iter->second->geometry->update(); // second->update();

	std::map<std::string, PagedObjects*>::iterator iter;
	for(iter = mFoliage.begin(); iter != mFoliage.end(); iter++) {

		TiXmlElement* mObject;
		mObject = new TiXmlElement("PagedObject");  
		mElem->LinkEndChild(mObject);
		
		mObject->SetAttribute("name",iter->second->name.c_str());

		

		if(iter->second->isGrass) {

			//std::string name
			//Real pageSize
			//Real batchDistance
			//std::string materialName
			//Real minScale
			//Real maxScale
			//bool animated
			//Real swayLenght
			//Real swaySpeed
			//Real density
			//GrassTechnique grt
			//FadeTechnique ft

			mObject->SetAttribute("isGrass","true");
			mObject->SetAttribute("isTree","false");
			mObject->SetAttribute("pageSize",Ogre::StringConverter::toString(iter->second->pageSize).c_str());
			mObject->SetAttribute("batchDistance",Ogre::StringConverter::toString(iter->second->batchDistance).c_str());
			mObject->SetAttribute("materialName",iter->second->materialName.c_str());
			mObject->SetAttribute("minScale",Ogre::StringConverter::toString(iter->second->minScale).c_str());
			mObject->SetAttribute("maxScale",Ogre::StringConverter::toString(iter->second->maxScale).c_str());
			mObject->SetAttribute("animated",Ogre::StringConverter::toString(iter->second->animated).c_str());
			mObject->SetAttribute("swayLenght",Ogre::StringConverter::toString(iter->second->swayLenght).c_str());
			mObject->SetAttribute("swaySpeed",Ogre::StringConverter::toString(iter->second->swaySpeed).c_str());
			mObject->SetAttribute("density",Ogre::StringConverter::toString(iter->second->density).c_str());
			
			if(iter->second->grt == GRASSTECH_CROSSQUADS)
				mObject->SetAttribute("GrassTechnique","GRASSTECH_CROSSQUADS");

			if(iter->second->grt == GRASSTECH_QUAD)
				mObject->SetAttribute("GrassTechnique","GRASSTECH_QUAD");

			if(iter->second->grt == GRASSTECH_SPRITE)
				mObject->SetAttribute("GrassTechnique","GRASSTECH_SPRITE");

			if(iter->second->ft == FADETECH_ALPHA)
				mObject->SetAttribute("FadeTechnique","FADETECH_ALPHA");

			if(iter->second->ft == FADETECH_ALPHAGROW)
				mObject->SetAttribute("FadeTechnique","FADETECH_ALPHAGROW");

			if(iter->second->ft == FADETECH_GROW)
				mObject->SetAttribute("FadeTechnique","FADETECH_GROW");

		}
		if(iter->second->isTree) {

			//std::string name
			//Real pageSize
			//Real batchDistance
			//Real batchFade
			//Real impostorDist
			//Real impostorFade
			//std::string meshName
			//unsigned int quantity
			//Real minScale
			//Real maxScale
			mObject->SetAttribute("isGrass","false");
			mObject->SetAttribute("isTree","true");
			mObject->SetAttribute("pageSize",Ogre::StringConverter::toString(iter->second->pageSize).c_str());
			mObject->SetAttribute("batchDistance",Ogre::StringConverter::toString(iter->second->batchDistance).c_str());
			mObject->SetAttribute("batchFade",Ogre::StringConverter::toString(iter->second->batchFade).c_str());
			mObject->SetAttribute("impostorDist",Ogre::StringConverter::toString(iter->second->impostorDist).c_str());
			mObject->SetAttribute("impostorFade",Ogre::StringConverter::toString(iter->second->impostorFade).c_str());
			mObject->SetAttribute("meshName",iter->second->meshName.c_str());
			mObject->SetAttribute("quantity",Ogre::StringConverter::toString(iter->second->quantity).c_str());
			mObject->SetAttribute("minScale",Ogre::StringConverter::toString(iter->second->minScale).c_str());
			mObject->SetAttribute("maxScale",Ogre::StringConverter::toString(iter->second->maxScale).c_str());
		
			TreeIterator2D trees = iter->second->treeLoader; 
			while (trees.hasMoreElements()) {
				TreeRef tr = trees.getNext();
				Vector3 pos = tr.getPosition();
				
				TiXmlElement* mTree;
				mTree = new TiXmlElement("Tree");  
				mObject->LinkEndChild(mTree);

				mTree->SetAttribute("position",Ogre::StringConverter::toString(pos).c_str());
				
			}

		}
	}

}
